package cn.jussi.dao;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import cn.jussi.utils.JdbcUtils;

/**
 * Dao的基本类，用于被具体的Dao类继承
 * @author 范俊熙
 *
 * @param <T>
 * 		针对要操作各张数据表映射到Java工程里的Java类
 */
public class BaseDao<T> {
	
	QueryRunner queryRunner = new QueryRunner();
	
	/**
	 * 泛型的类型
	 */
	private Class<T> clazz;
	
	/**
	 * 泛型的类型的获取方法
	 */
	@SuppressWarnings("unchecked")
	public BaseDao() {
		//这个 this 是子类的对象，getGenericSuperclass()，即得到本类的类型
		Type superType = this.getClass().getGenericSuperclass();
		if(superType instanceof ParameterizedType) {
			ParameterizedType pt = (ParameterizedType) superType;
			//返回一个类型数组，第一个元素就是我们要的clazz
			Type[] tarry = pt.getActualTypeArguments();
			if(tarry[0] instanceof Class) {
				clazz = (Class<T>) tarry[0];
			}
		}
	}	
	
	/**
	 * 通用的不带事务的查询方法,取出sql语句结果集的第一条数据，封装成一个类返回
	 * 用到 dbutils
	 * clazz应传入BaseDao<T>里的T的真正用的时候的Class
	 * @param sql
	 * @param args
	 * @return
	 */
	public T get(String sql, Object... args) {
		Connection conn = null;
		T entity = null;
		try {
			conn = JdbcUtils.getConnection();
			entity = queryRunner.query(conn, sql, new BeanHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return entity;
	}
	
	/**
	 * 通用的带事务处理的查询方法,取出sql语句结果集的第一条数据，封装成一个类返回
	 * 用到 dbutils
	 * clazz应传入BaseDao<T>里的T的真正用的时候的Class
	 * @param sql
	 * @param args
	 * @return
	 */
	public T get(Connection conn, String sql, Object... args) {
		T entity = null;
		try {
			entity = queryRunner.query(conn, sql, new BeanHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return entity;
	}
	
	/**
	 * 获得多条记录的通用方法
	 * @param sql
	 * @param args
	 * @return
	 */
	public List<T> getList(String sql, Object... args) {
		Connection conn = null;
		List<T> list = null;
		try {
			conn = JdbcUtils.getConnection();
			list = queryRunner.query(conn, sql, new BeanListHandler<T>(clazz), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return list;
	}
	
	/**
	 * 实现insert、update、delete的通用更新方法
	 * @param sql
	 * @param args
	 * @return
	 */
	public int update(String sql, Object... args) {
		Connection conn = null;
		int rows = 0;
		try {
			conn = JdbcUtils.getConnection();
			rows = queryRunner.update(conn, sql, args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return rows;
	}

	/**
	 * 通常返回值只有一个数值的查询，ex:count(id)
	 * @param sql
	 * @param args
	 * @return
	 */
	public Object getValue(String sql, Object... args) {
		Connection conn = null;
		Object obj = null;
		try {
			conn = JdbcUtils.getConnection();
			obj = queryRunner.query(conn, sql, new ScalarHandler<>(), args);
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			JdbcUtils.closeConn(conn);
		}
		return obj;
	}
}
